package org.i9.slb.platform.anseko.provider.utils;

import com.alibaba.fastjson.JSONObject;
import org.i9.slb.platform.anseko.common.BusinessException;
import org.i9.slb.platform.anseko.common.ErrorCode;
import org.i9.slb.platform.anseko.downstream.dto.param.ShellCommandParamDto;
import org.i9.slb.platform.anseko.downstream.dto.result.CommandExecuteReDto;
import org.i9.slb.platform.anseko.provider.remote.CoreserviceRemoteService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;

/**
 * shell命令执行工具类
 *
 * @author R12
 * @date 2018.08.29
 */
public class ShellCommandUtil {

    public static CommandExecuteReDto shellExecuteLocal(ShellCommandParamDto shellCommandParamDto) throws Exception {
        CommandExecuteReDto commandExecuteReDto = new CommandExecuteReDto();
        commandExecuteReDto.setCommandId(shellCommandParamDto.getCommandId());
        try {
            logger.info("shellExecuteLocal 远程服务, param : {}, 开始", JSONObject.toJSONString(shellCommandParamDto));
            ResultExcecution resultExcecution = ShellCommandUtil.shellExecuteLocal(shellCommandParamDto.getCommandLine());
            commandExecuteReDto.setExecuteResult(resultExcecution.getExecuteResult());
        } catch (BusinessException e) {
            logger.error("shellExecuteLocal 远程服务, param : {}, 异常", JSONObject.toJSONString(shellCommandParamDto), e);
            commandExecuteReDto.setExecuteResult(ExceptionUtils.exceptionToString(e));
            throw e;
        } catch (Exception e) {
            logger.error("shellExecuteLocal 远程服务, param : {}, 异常", JSONObject.toJSONString(shellCommandParamDto), e);
            commandExecuteReDto.setExecuteResult(ExceptionUtils.exceptionToString(e));
            throw e;
        } finally {
            CoreserviceRemoteService coreserviceRemoteService = SpringContextUtil.getBean(CoreserviceRemoteService.class);
            coreserviceRemoteService.remoteServiceCallbackCommandDispatch(commandExecuteReDto);
        }
        return commandExecuteReDto;
    }

    public static ResultExcecution shellExecuteLocal(String remoteCommand) {
        try {
            StringWriter swriter = new StringWriter();
            Process process = exec(remoteCommand);
            process.waitFor();
            Reader reader = new InputStreamReader(process.getInputStream());
            char[] chars = new char[16];
            int read = -1;
            while ((read = reader.read(chars)) > -1) {
                swriter.write(chars, 0, read);
            }
            String executeResult = swriter.toString().trim();
            ResultExcecution resultExcecution = new ResultExcecution(remoteCommand, executeResult);
            logger.info("execute:" + remoteCommand + " executeResult : " + executeResult);
            return resultExcecution;
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.SHELL_PROCESS_ERROR, "执行命令失败", e);
        }
    }

    private static Process exec(String remoteCommand) throws IOException {
        Runtime runtime = Runtime.getRuntime();
        return runtime.exec(new String[]{"/bin/sh", "-c", remoteCommand});
    }

    private static final Logger logger = LoggerFactory.getLogger(ShellCommandUtil.class);
}
